package com.yangleping.springframework.aop.framework;

import com.yangleping.springframework.aop.AdvisedSupport;
import com.yangleping.springframework.util.ClassUtils;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 使用 CGLIB 实现的 AOP 代理类。
 * 该类通过 CGLIB 动态生成目标类的子类来实现代理功能。
 *
 * @author yangleping
 */
public class Cglib2AopProxy implements AopProxy {

    /**
     * 包含 AOP 配置信息的支持类。
     */
    private final AdvisedSupport advised;

    /**
     * 构造函数，用于初始化 Cglib2AopProxy。
     *
     * @param advised 包含 AOP 配置信息的支持类。
     */
    public Cglib2AopProxy(AdvisedSupport advised) {
        this.advised = advised;
    }

    /**
     * 获取代理对象。
     *
     * @return 生成的代理对象。
     */
    @Override
    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        Class<?> aClass = advised.getTargetSource().getTarget().getClass();
        aClass = ClassUtils.isCglibProxyClass(aClass)? aClass.getSuperclass():aClass;
        enhancer.setSuperclass(aClass);
        enhancer.setInterfaces(advised.getTargetSource().getTargetClass());
        enhancer.setCallback(new DynamicAdvisedInterceptor(advised));
        Object o = null;
        try {
            o = enhancer.create();
        } catch (Exception e) {
            System.out.println("beanName：" + " cglibBean创建过程出错");
            e.printStackTrace();
        }
        return o;
//        return enhancer.create();
    }

    /**
     * 动态代理拦截器，实现了 CGLIB 的 MethodInterceptor 接口。
     */
    private static class DynamicAdvisedInterceptor implements MethodInterceptor {

        /**
         * 包含 AOP 配置信息的支持类。
         */
        private final AdvisedSupport advised;

        /**
         * 构造函数，用于初始化 DynamicAdvisedInterceptor。
         *
         * @param advised 包含 AOP 配置信息的支持类。
         */
        public DynamicAdvisedInterceptor(AdvisedSupport advised) {
            this.advised = advised;
        }

        /**
         * 拦截方法调用。
         *
         * @param o 目标对象。
         * @param method 被调用的方法。
         * @param objects 方法参数。
         * @param methodProxy 方法代理。
         * @return 方法调用的结果。
         * @throws Throwable 如果方法调用过程中发生异常。
         */
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            CglibMethodInvocation methodInvocation = new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, objects, methodProxy);
            if (advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) {
                return advised.getMethodInterceptor().invoke(methodInvocation);
            }
            return methodInvocation.proceed();
        }
    }

    /**
     * CGLIB 方法调用封装类，继承自 ReflectiveMethodInvocation。
     */
    private static class CglibMethodInvocation extends ReflectiveMethodInvocation {

        /**
         * 方法代理。
         */
        private final MethodProxy methodProxy;

        /**
         * 构造函数，用于初始化 CglibMethodInvocation。
         *
         * @param target 目标对象。
         * @param method 被调用的方法。
         * @param arguments 方法参数。
         * @param methodProxy 方法代理。
         */
        public CglibMethodInvocation(Object target, Method method, Object[] arguments, MethodProxy methodProxy) {
            super(target, method, arguments);
            this.methodProxy = methodProxy;
        }

        /**
         * 继续调用方法。
         *
         * @return 方法调用的结果。
         * @throws Throwable 如果方法调用过程中发生异常。
         */
        @Override
        public Object proceed() throws Throwable {
            return this.methodProxy.invoke(this.target, this.arguments);
        }
    }
}
